package scales.xml.parser.sax
import org.xml.sax.Locator
import org.xml.sax.ext.Locator2
import scales.xml._
import parser._
import scales.xml.parser.strategies.{PathOptimisationStrategy, OptimisationToken}
import scales.xml.impl.{NotFromParser, IsFromParser, FromParser}
import impl.{NameCreators, TreeProxies}
class Handler[Token <: OptimisationToken](strategy : PathOptimisationStrategy[Token])(implicit val defaultVersion : XmlVersion) extends org.xml.sax.ext.DefaultHandler2 {
import scales.xml.ScalesXml.xmlCBF
import scales.utils.{noPath, top, ScalesUtils }
import scales.utils.collection.path.Path
import org.xml.sax._
import scala.collection.immutable.Stack
import ScalesUtils._
import NameCreators._
private[this] implicit val weAreInAParser : FromParser = IsFromParser
private[this] val token : Token = strategy.createToken
private[this] val buf = new TreeProxies()
def getBuf = buf
private[this] var isCData = false
private[this] var nsDeclarations = emptyNamespaces
private[this] var prolog = Prolog()
private[this] var end = EndMisc()
def getProlog = prolog
def getEnd = end
private[this] var locator : Locator = _
private[this] var inprolog = true
def checkit(what: String) {
}
override def startDTD(name : String, publicId : String, systemId : String) {
prolog = prolog.copy(dtd = Some(DTD(name, publicId, systemId)))
}
override def processingInstruction(target : String, data : String) {
val pi = PI(target, data)
addMisc(Right(pi))
}
override def startPrefixMapping(prefix: String, uri: String) {
nsDeclarations += (prefix -> uri)
}
override def setDocumentLocator( loc : Locator ) {
locator = loc
}
override def startElement(uri: String,
localName: String,
qName: String,
attributes: org.xml.sax.Attributes) {
if (inprolog) {
if (locator.isInstanceOf[Locator2]) {
val loc2 = locator.asInstanceOf[Locator2]
prolog = prolog.copy( decl = prolog.decl.copy(encoding = (
if (loc2.getEncoding ne null) {
java.nio.charset.Charset.forName(loc2.getEncoding)
} else scales.utils.defaultCharset
)))
}
}
inprolog = false
var i = 0
val length = attributes.getLength
val attrs = strategy.attributeArray(length, token)
while (i < length) {
val qname = aqn(attributes.getURI(i), attributes.getLocalName(i), attributes.getQName(i), strategy, token)
attrs.update(i,
strategy.attribute(qname,
attributes.getValue(i),
token)
)
i += 1
}
val attribs = scales.xml.impl.AttributeSet.unsafe(attrs, length)
val elem = strategy.elem(
eqn(uri, localName, qName, strategy, token)
, attribs, nsDeclarations, token)
nsDeclarations = emptyNamespaces
strategy.beginSubTree(buf, elem, token)
}
override def endElement(uri: String,
localName: String,
qName: String) {
strategy.elementEnd(buf, token)
}
override def comment(ch: Array[Char], offset: Int, length: Int): Unit = {
val text = new String(ch, offset, length)
addMisc( Left(Comment(text)) )
}
def addMisc( miscItem : Misc ) {
if (inprolog)
prolog = prolog.copy(misc = prolog.misc :+ miscItem)
else {
if (buf.depth == -1)
end = end.copy( misc = end.misc :+ miscItem)
else
buf.addChild( miscItem.fold[XmlItem](x=>x, y=>y))
}
}
override def characters(ch: Array[Char], offset: Int, length: Int): Unit = {
val text = new String(ch, offset, length)
val child: XmlItem = if (isCData) CData(text) else Text(text)
buf.addChild(child)
}
override def startCDATA() { isCData = true; }
override def endCDATA() { isCData = false; }
}